package com.fh.shop.api.order.biz;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.fh.shop.api.cart.vo.CartItemVo;
import com.fh.shop.api.cart.vo.CartVo;
import com.fh.shop.api.common.ResponseEnum;
import com.fh.shop.api.common.ServerResponse;
import com.fh.shop.api.common.SystemConst;
import com.fh.shop.api.exception.StockException;
import com.fh.shop.api.order.mapper.IOrderDetailMapper;
import com.fh.shop.api.order.mapper.IOrderMapper;
import com.fh.shop.api.order.param.OrderParam;
import com.fh.shop.api.order.po.Order;
import com.fh.shop.api.order.po.OrderDetail;
import com.fh.shop.api.product.mapper.IProductMapper;
import com.fh.shop.api.product.po.Product;
import com.fh.shop.api.recipient.po.Recipient;
import com.fh.shop.api.util.KeyUtil;
import com.fh.shop.api.util.RedisUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service("orderService")
@Transactional(rollbackFor = Exception.class)
public class IOrderServiceImpl implements IOrderService {

    @Resource
    private IOrderMapper orderMapper;
    @Resource
    private IOrderDetailMapper orderDetailMapper;
    @Resource
    private IProductMapper productMapper;

    //添加订单
    @Override
    public ServerResponse addOrder(OrderParam orderParam) {
        //非空判断
        Long memberId = orderParam.getMemberId();
        Long recipientId = orderParam.getRecipientId();
        Integer payType = orderParam.getPayType();
        if (recipientId == null || payType == null){
            return ServerResponse.error(ResponseEnum.ORDER_INFO_IS_NULL);
        }
        //会员对应的购物车是否存在
        String cartKey = KeyUtil.buildCartKey(memberId);
        boolean exist = RedisUtil.exist(cartKey);
        if (!exist){
            return ServerResponse.error(ResponseEnum.ORDER_CART_IS_ERROR);
        }
        //收件人是否存在
        String recipientKey = KeyUtil.buildRecipientKey(memberId);
        String recipientListJson = RedisUtil.get(recipientKey);
        List<Recipient> recipientList = JSON.parseArray(recipientListJson, Recipient.class);
        Optional<Recipient> recipientOptional = recipientList.stream().filter(x -> x.getId().longValue() == recipientId.longValue()).findFirst();
        if (!recipientOptional.isPresent()){
            return ServerResponse.error(ResponseEnum.ORDER_RECIPIENT_IS_ERROR);
        }
        //获取收件人 [从redis中获取的]
        Recipient recipient = recipientOptional.get();
        //判断库存是否充足
        String cartJson = RedisUtil.hget(cartKey, SystemConst.CART_MCONENT);
        CartVo cartVo = JSON.parseObject(cartJson, CartVo.class);
        List<CartItemVo> cartItemVoList = cartVo.getCartItemVoList();
        List<Long> idList = cartItemVoList.stream().map(x -> x.getProductId()).collect(Collectors.toList());
        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id","stock");
        queryWrapper.in("id",idList);
        List<Product> productList = productMapper.selectList(queryWrapper);
        // 用来存放库存不足的商品名字 集合
        List<String> productNames = new ArrayList<>();
        for (Product product : productList) {
            //和购物车中购买的商品的数量进行对比
            Optional<CartItemVo> optionalCartItemVo = cartItemVoList.stream().filter(x -> x.getProductId().longValue() == product.getId().longValue()).findFirst();
            if (optionalCartItemVo.isPresent()){
                CartItemVo cartItemVo = optionalCartItemVo.get();
                //如果 购买的商品 大于 商品的库存
                if (cartItemVo.getCount().longValue() > product.getStock().longValue()){
                    productNames.add(cartItemVo.getProductName());
                }
            }
        }
        if (productNames.size() > 0){
            //将商品不足的集合响应给前台
            return ServerResponse.error(ResponseEnum.ORDER_STOCK_IS_ERROR, StringUtils.join(productNames,","));
        }
        //减库存 [循环 购物车的商品]
        for (CartItemVo cartItemVo : cartItemVoList) {
            Long productId = cartItemVo.getProductId();
            Long count = cartItemVo.getCount();
            int rows = productMapper.updateStock(productId,count);
            // 库存为0，这个商品已买完了
            if (rows == 0){
                productNames.add(cartItemVo.getProductName());
            }
        }
        if (productNames.size() > 0){
            //将商品不足的集合响应给前台 【抛异常：1 响应前台信息提示 2回滚之前的更新】 【业务；要么都下单成功，要么都不下单成功】
            throw new StockException(ResponseEnum.ORDER_STOCK_IS_ERROR_LOCK, StringUtils.join(productNames,","));
           // return ServerResponse.error(ResponseEnum.ORDER_STOCK_IS_ERROR, StringUtils.join(productNames,","));
        }
        //插入订单表
        String id = insertOrder(memberId, payType, recipient, cartVo);
        //插入订单明细表 [批量插入]
        insertOrderDetail(cartItemVoList, id);
        //删除redis中的购物车
        RedisUtil.delete(cartKey);
        return ServerResponse.success();
    }


    //查询订单
    @Override
    public ServerResponse findOrderList(Long memberId) {
        QueryWrapper<Order> orderQueryWrapper = new QueryWrapper<>();
        orderQueryWrapper.select("id","totalPrice","createTime","orderStatus","recipientName","recipientAddr","recipientPhone");
        orderQueryWrapper.eq("memberId",memberId);
        List<Order> orders = orderMapper.selectList(orderQueryWrapper);
        return ServerResponse.success(orders);
    }


    //插入订单明细表 [批量插入]
    private void insertOrderDetail(List<CartItemVo> cartItemVoList, String id) {
        List<OrderDetail> orderDetailList = cartItemVoList.stream().map(x -> {
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderId(id);
            orderDetail.setImage(x.getImage());
            orderDetail.setSubPrice(new BigDecimal(x.getSubTotal()));
            orderDetail.setPrice(new BigDecimal(x.getPrice()));
            orderDetail.setProductId(x.getProductId());
            orderDetail.setProductName(x.getProductName());
            orderDetail.setCount(x.getCount());
            return orderDetail;
        }).collect(Collectors.toList());
        orderDetailMapper.addBatch(orderDetailList);
    }

    //插入订单表
    private String insertOrder(Long memberId, Integer payType, Recipient recipient, CartVo cartVo) {
        //插入订单表
        Order order = new Order();
        // String类型的唯一标识 主键 【雪花算法 mp中封装的】
        String id = IdWorker.getIdStr();
        // 手工设置的  唯一标识
        order.setId(id);
        order.setRecipientName(recipient.getRecipientName());
        order.setRecipientPhone(recipient.getPhone());
        order.setRecipientAddr(recipient.getAddr());
        order.setRecipientId(recipient.getId());
        order.setCreateTime(new Date());
        order.setPayType(payType);
        order.setMemberId(memberId);
        String totalPrice = cartVo.getTotalPrice();
        order.setTotalPrice(new BigDecimal(totalPrice));
        Long totalCount = cartVo.getTotalCount();
        order.setTotalCount(totalCount);
        order.setOrderStatus(SystemConst.OrderStatus.WAIT_PAY);
        orderMapper.insert(order);
        return id;
    }
}
